import {ChangeDetectionStrategy, Component, OnInit} from '@angular/core';
import {User} from "../../@core/data/user";
import {NzButtonModule} from "ng-zorro-antd/button";
import {NzTableComponent, NzTableModule} from "ng-zorro-antd/table";
import {CommonModule, NgForOf} from "@angular/common";
import {NzSpaceModule} from "ng-zorro-antd/space";
import {UserModalComponent} from "../user-modal/user-modal.component";
import {NzModalModule, NzModalService} from "ng-zorro-antd/modal";
import {NzFormModule} from "ng-zorro-antd/form";
import {NzIconModule} from "ng-zorro-antd/icon";
import {Router} from "@angular/router";
import {NzPopconfirmDirective} from "ng-zorro-antd/popconfirm";
import {NzDividerComponent} from "ng-zorro-antd/divider";
import {BehaviorSubject, catchError, combineLatest, EMPTY, map, Observable, scan, Subject, switchMap, tap} from "rxjs";
import {FormsModule} from "@angular/forms";
import {NzInputDirective} from "ng-zorro-antd/input";
import {NzInputNumberComponent} from "ng-zorro-antd/input-number";
import {UserService} from "../user.service";
import {NzMessageService} from "ng-zorro-antd/message";
import {ActionTypes, UserAddEvent, UserEvent, UserRemoveEvent, UserUpdateEvent} from "./data.t";

@Component({
  selector: 'app-user-table',
  templateUrl: './user-table.component.html',
  standalone: true,
  imports: [
    CommonModule,
    NzTableComponent,
    NgForOf,
    NzSpaceModule,
    UserModalComponent,
    NzModalModule,
    NzTableModule,
    NzFormModule,
    NzButtonModule,
    NzIconModule,
    NzPopconfirmDirective,
    NzDividerComponent,
    FormsModule,
    NzInputDirective,
    NzInputNumberComponent
  ],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class UserTableComponent implements OnInit {

  realNameSource = new BehaviorSubject<string>('')
  ageSource = new BehaviorSubject<number | undefined>(undefined)
  addressSource = new BehaviorSubject('')
  totalSource = new BehaviorSubject<number>(0)
  loadingSource = new BehaviorSubject<boolean>(false)
  users$!: Observable<User[]>
  private pageNumberSource = new BehaviorSubject<number>(1);
  private pageSizeSource = new BehaviorSubject<number>(10);
  private userQueryReqSource = new BehaviorSubject<User>({})
  private userEventSource = new Subject<UserEvent>()
  private remoteUsers$: Observable<User[]> = combineLatest([this.pageSizeSource, this.pageNumberSource, this.userQueryReqSource])
    .pipe(
      map(([pageSize, pageNumber, userQueryReq]) => ({pageSize, pageNumber, userQueryReq})),
      switchMap(({pageSize, pageNumber, userQueryReq}) => {
        return this.userService.getUserList(userQueryReq, pageNumber, pageSize)
          .pipe(
            tap(() => {
              this.loadingSource.next(false)
            }),
            map(res => {
              // 不属于副作用，不应该放在 tap 中
              this.totalSource.next(res.totalElements)
              return res.content
            }),
            catchError(error => {
              this.messageService.error('查询失败：' + error.message)
              return EMPTY
            })
          )
      })
    );

  constructor(private router: Router,
              private userService: UserService,
              private messageService: NzMessageService,
              private modalService: NzModalService) {
  }

  ngOnInit() {
    this.remoteUsers$.subscribe(users => {
      // 远端数据来的时候，重新赋值 users$
      this.userEventSource.next({
        type: ActionTypes.INIT,
        users: users
      })
    })
    this.users$ = this.userEventSource.pipe(
      scan((acc: User[], event: UserEvent) => {
        return this.processUsers(acc, event)
      }, [])
    )
  }

  processUsers(acc: User[], event: UserEvent) {
    if (event.type == ActionTypes.INIT) {
      acc = event.users!
    }
    switch (event.type) {
      case ActionTypes.REMOVE_USER:
        // 删除用户
        this.totalSource.next(this.totalSource.value - 1)
        let {uid} = event as UserRemoveEvent
        return acc.filter(user => user.id !== uid)
      case ActionTypes.ADD_USER:
        // 新增用户
        this.totalSource.next(this.totalSource.value + 1)
        let {user: addUser} = event as UserAddEvent
        return [addUser, ...acc];
      case ActionTypes.UPDATE_USER:
        // 修改用户
        let {user: newUser} = event as UserUpdateEvent
        return acc.map(oldUser => oldUser.id === newUser.id ? newUser : oldUser);
      default:
        return acc;
    }
  }

  /**
   * 创建模态框
   */
  createModal(isEdit: boolean, user?: User) {
    const modal = this.modalService.create({
      nzTitle: isEdit ? '修改用户' : '新增用户',
      nzContent: UserModalComponent,
      nzOkText: null,
      nzCancelText: null,
      nzData: {
        isEdit: isEdit,
        user: user
      }
    })
    modal.afterClose.subscribe((result: User) => {
      if (result) {
        let userEvent: UserEvent;
        if (isEdit) {
          // 编辑就发编辑事件
          userEvent = {
            type: ActionTypes.UPDATE_USER,
            user: result
          } as UserUpdateEvent
        } else {
          // 发新增事件
          userEvent = {
            type: ActionTypes.ADD_USER,
            user: result
          } as UserAddEvent
        }
        this.userEventSource.next(userEvent)
      }
    })
  }

  /**
   * 跳转到详情页
   * @param user
   */
  handleDetail(user: User) {
    this.router.navigate([`/userInfo/${String(user.id)}`])
  }

  /**
   * 搜索框发生改变--姓名
   * @param realName
   */
  realNameChange(realName: string) {
    this.realNameSource.next(realName)
  }

  /**
   * 搜索框发生改变--年龄
   * @param age
   */
  ageChange(age: number) {
    this.ageSource.next(age)
  }

  /**
   * 搜索框发生改变--地址
   * @param address
   */
  addressChange(address: string) {
    this.addressSource.next(address)
  }

  /**
   * 重置按钮
   */
  handleReset() {
    this.realNameSource.next('')
    this.ageSource.next(undefined)
    this.addressSource.next('')
    this.userQueryReqSource.next({
      realName: '',
      age: undefined,
      address: ''
    })
    this.pageNumberSource.next(1);
  }

  /**
   * 查询按钮
   */
  handleQuery() {
    this.loadingSource.next(true)
    let userQueryReq: User = {
      realName: this.realNameSource.value,
      age: this.ageSource.value,
      address: this.addressSource.value
    }
    this.userQueryReqSource.next(userQueryReq)
    if (userQueryReq.realName || userQueryReq.age || userQueryReq.address) {
      this.pageNumberSource.next(1);
    }
  }

  /**
   * 页码发生改变
   */
  pageIndexChange = (index: number) => {
    this.pageNumberSource.next(index)
  }

  /**
   * 页数发生改变
   */
  pageSizeChange = (size: number) => {
    this.pageSizeSource.next(size)
  }

  handleRemove(data: User) {
    if (data.id) {
      this.userService.removeUser(data.id)
        .subscribe({
            next: () => {
              let userRemoveEvent = {
                type: ActionTypes.REMOVE_USER,
                uid: data.id
              }
              // 删除成功，通知 users$
              this.userEventSource.next(userRemoveEvent)
              this.messageService.success('删除成功')
            },
            error: (error) => {
              this.messageService.error('删除失败：' + error.message)
            }
          }
        )
    }
  }
}
